package service

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	constant "rongyy/src/constants"
	"rongyy/src/middlewares"
	"rongyy/src/models"
	"strconv"
	"time"
)

type OutPatientService struct {
}

func (pc *OutPatientService) GetAdmByCardNo(req *models.Req4902Params) (*models.Resp4902, error) {
	data, err := (&HisService{}).GetAdmByCardNo(req)
	if data.ResultCode != "0" {
		return nil, errors.New(data.ResultMsg)
	}
	if err != nil {
		middlewares.Logger.Println("Unmarshal resp3013 failed ", err)
		return nil, err
	}
	return data, nil
}

func (pc *OutPatientService) GetMenteAdm(req *models.Req0050Params) (*models.Resp4902, error) {
	data, err := (&HisService{}).GetMenteAdm(req)
	if err != nil {
		middlewares.Logger.Println("Unmarshal resp3013 failed ", err)
		return nil, err
	}
	return data, nil
}

func (pc *OutPatientService) GetChargeOrder(req *models.Req4904Params) (*models.Resp4904, error) {
	data, err := (&HisService{}).GetChargeOrder(req)
	if err != nil {
		middlewares.Logger.Println("Unmarshal resp3013 failed ", err)
		return nil, err
	}
	// 处理撤销订单
	if data.ResultCode != "0" && data.ResultMsg == "存在已经预结算的结算单，请完成结算或撤销后重新结算" {
		opo, has, err := (&models.PrescriptionModel{}).FindByAdm(req.Adm)
		if !has {
			return nil, errors.New(data.ResultMsg)
		}

		if err != nil {
			return nil, err
		}

		if opo.Status == "prepay" && opo.PayStatus == "paying" {
			current := time.Now().Unix()
			t, err := time.ParseInLocation("2006-01-02 15:04:05", opo.CreatedAt.String(), time.Local)
			if err != nil {
				return nil, err
			}
			diff := current - t.Unix()
			fmt.Println(diff)
			if diff < 60 {
				return nil, errors.New("订单正在支付中，请1分钟后重试")
			}
		}

		new := &models.Resp4904{
			PayOrdCount: "1",
			PayOrdList:  opo.PayOrdList,
			ResultCode:  "0",
		}
		return new, nil
		//invoiceNo := opo.InvoiceNo
		//
		//reqCancel := &models.Req4910Params{
		//	PatientId:    req.PatientId,
		//	InvoiceNoStr: invoiceNo,
		//	OrderNo:      opo.OrderNo,
		//}
		//cancelData, err := (&HisService{}).CancelCharge(reqCancel)
		//if err != nil {
		//	return nil, err
		//}
		//if cancelData.ResultCode == "0" {
		//	new, err := (&HisService{}).GetChargeOrder(req)
		//	if err != nil {
		//		middlewares.Logger.Println("Unmarshal resp3013 failed ", err)
		//		return nil, err
		//	}
		//	return new, nil
		//}
	}
	if data.ResultCode != "0" {
		return nil, errors.New(data.ResultMsg)
	}
	return data, nil
}

func (pc *OutPatientService) PreBillCharge(req *models.Req4905Params) (*models.Resp4905, error) {
	data, err := (&HisService{}).PreBillCharge(req)
	if err != nil {
		middlewares.Logger.Println("Unmarshal resp3013 failed ", err)
		return nil, err
	}
	if data.ResultCode != "0" {
		return nil, errors.New(data.ResultMsg)
	}
	return data, nil
}

func (pc *OutPatientService) CompleteCharge(req *models.Req4906Params) (*models.Resp4906, error) {
	data, err := (&HisService{}).CompleteCharge(req)
	if data.ResultCode != "0" {
		return nil, errors.New("门诊确认收费失败")
	}
	reqOp := &models.PrescriptionModel{
		OrderNo:   req.OrderNo,
		OrderSn:   req.OrderSn,
		PatientId: req.PatientId,
		Status:    "confirm",
		PayStatus: "paid",
		UpdatedBy: req.UpdatedBy,
		InvoiceNo: req.InvoiceNoStr,
	}
	err = reqOp.Confirm()
	if err != nil {
		middlewares.Logger.Println("Unmarshal resp3013 failed ", err)
		return nil, err
	}
	opm := &models.OpPreModel{
		OrderNo:   req.OrderNo,
		PatientId: req.PatientId,
		Status:    "done",
		InvoiceNo: req.InvoiceNoStr,
		OrderSn:   req.OrderSn,
	}
	(&models.PrescriptionModel{}).UpdatePre(opm)
	return data, nil
}

func (pc *OutPatientService) GetPaidRecord(req *models.Req4907Params) (*models.Resp4907, error) {
	data, err := (&HisService{}).GetPaidRecord(req)
	if err != nil {
		middlewares.Logger.Println("Unmarshal resp3013 failed ", err)
		return nil, err
	}
	return data, nil
}

func (pc *OutPatientService) GetPaidRecordDetails(req *models.Req4908Params) (*models.Resp4908, error) {
	data, err := (&HisService{}).GetPaidRecordDetails(req)
	if err != nil {
		middlewares.Logger.Println("Unmarshal resp3013 failed ", err)
		return nil, err
	}
	if data.ResultCode != "0" {
		return nil, errors.New(data.ResultMsg)
	}
	return data, nil
}

func (pc *OutPatientService) CancelCharge(req *models.Req4910Params) (*models.Resp4910, error) {
	//data, err := (&HisService{}).CancelCharge(req)
	//if err != nil {
	//	middlewares.Logger.Println("Unmarshal resp3013 failed ", err)
	//	return nil, err
	//}
	//// 更新订单状态
	//if data.ResultCode == "0" {
	pm := models.PrescriptionModel{
		PatientId: req.PatientId,
		InvoiceNo: req.InvoiceNoStr,
		OrderSn:   req.OrderSn,
	}
	err := pm.CancelPreOrder()
	if err != nil {
		middlewares.Logger.Println("CancelPreOrder failed ", err)
		return nil, err
	}
	//}
	return nil, nil
}

// CancelChargeManual
//
//	@Description: 手动取消预结算
//	@receiver pc
//	@param req
//	@return *models.Resp4910
//	@return error
func (pc *OutPatientService) CancelChargeManual(req *models.Req4910Params) (*models.Resp4910, error) {
	op := &models.PrescriptionModel{}
	opdata, has, err := op.FindByOrderNo(req.OrderNo)
	if !has {
		return nil, errors.New("订单不存在")
	}
	if opdata.PayStatus == "paid" && opdata.Status == "confirm" {
		return nil, errors.New("医嘱已缴费成功")
	}
	req.InvoiceNoStr = opdata.InvoiceNo
	data, err := (&HisService{}).CancelCharge(req)
	if err != nil {
		middlewares.Logger.Println("Unmarshal resp3013 failed ", err)
		return nil, err
	}
	if data.ResultCode != "0" {
		return nil, errors.New(data.ResultMsg)
	}
	op.Remark = "患者手动取消预结算"
	op.OrderNo = req.OrderNo
	op.PatientId = req.PatientId
	op.OrderSn = req.OrderSn
	err = op.CancelPreOrder()
	if err != nil {
		middlewares.Logger.Println("CancelChargeManual failed ", err)
		return nil, err
	}
	return data, nil
}

func (op *OutPatientService) Refund(req *models.ReqOpRefundParams) (interface{}, error) {
	url := "https://testwxmp.zhongkangcloud.com/api/outpatientPayment/refundCallback"
	contentType := "application/soap+xml;charset=UTF-8"
	data := make(map[string]interface{})
	data["order_sn"] = req.OrderSn
	data["fee"] = req.Fee
	bytesData, _ := json.Marshal(data)
	resp, err := http.Post(url, contentType, bytes.NewReader(bytesData))
	if err != nil {
		middlewares.Logger.Println("Refund Post failed ", err)
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		middlewares.Logger.Println("read response body failed", err)
		return nil, err
	}
	type RefundResp struct {
		Success bool        `json:"success"`
		Data    interface{} `json:"data"`
		Errors  string      `json:"errors"`
	}

	rr := &RefundResp{}
	err = json.Unmarshal(body, rr)
	middlewares.Logger.Println(string(body))
	if err != nil {
		middlewares.Logger.Println("Unmarshal refundResp failed ", err)
		return nil, err
	}
	if !rr.Success {
		middlewares.Logger.Println("refundResp error ", rr.Errors)
		return nil, errors.New(rr.Errors)
	}

	return rr.Data, nil
}

func (pc *OutPatientService) PayOp(req *models.PrescriptionModel, ip string) (*models.PaymentRespData, string, string, error) {
	reqPre := &models.Req4905Params{
		PatientId: req.PatientId,
		OrderNo:   req.OrderNo,
		OrderSum:  req.OrderSum,
	}
	data, err := (&HisService{}).PreBillCharge(reqPre)
	if data.ResultCode != "0" {
		return nil, "", "", errors.New("预结算失败，请联系工作人员")
	}

	// 预结算成功，唤起支付,更新订单号

	rand.Seed(time.Now().UnixNano())
	t := rand.Intn(10000)
	ts := strconv.FormatInt(time.Now().UnixMicro(), 10)
	orderSn := "P" + ts + strconv.Itoa(t)
	fee, err := strconv.ParseFloat(req.OrderSum, 10)

	reqPay := &models.PaymentReq{
		MerchantId: constant.MerchantId,
		Desc:       req.OrderNo,
		PayStatus:  "unpaid",
		OutTradeNo: req.OrderNo,
		TotalFee:   fee,
		ClientIp:   ip,
		BusiType:   "reg",
		OrderSn:    orderSn,
		PayWay:     constant.PayWay,
		OpenId:     req.Openid,
	}

	payResp, err := (&PaymentService{}).Pay(reqPay)
	if err != nil {
		middlewares.Logger.Println("Unmarshal resp3013 failed ", err)
		return nil, "", "", err
	}
	if payResp.ERRCODE != "000000" {
		return nil, "", "", errors.New(payResp.ERRMSG)
	}
	//请求支付成功,入库
	req.Status = "prepay"
	req.PayStatus = "paying"
	req.InvoiceNo = data.InvoiceList[0].InvoiceNo
	req.InvoiceList = data.InvoiceList
	req.OrderSn = orderSn

	err = req.Create()
	if err != nil {
		middlewares.Logger.Println("Unmarshal resp3013 failed ", err)
		return nil, "", "", err
	}
	// 记录预结算入库
	pre, has, err := (&models.PrescriptionModel{}).FindPreByOrderNo(req.OrderNo)
	opm := &models.OpPreModel{
		OrderNo:     req.OrderNo,
		PatientId:   req.PatientId,
		Status:      "charge",
		InvoiceNo:   data.InvoiceList[0].InvoiceNo,
		InvoiceList: data.InvoiceList,
		ItemList:    req.ItemList,
		OrderSn:     orderSn,
	}
	if !has {
		(&models.PrescriptionModel{}).CreatePre(opm)
	}
	if has && pre.Status != "charge" {
		(&models.PrescriptionModel{}).CreatePre(opm)
	}

	if has && pre.Status == "charge" {
		(&models.PrescriptionModel{}).UpdatePre(opm)
	}
	return payResp, orderSn, req.InvoiceNo, nil
}

func (op *OutPatientService) QueryPrepay(req *models.PrescriptionModel) ([]models.OpPreModel, int64, error) {
	pm := &models.PrescriptionModel{}
	data, total, err := pm.FindPreByPatientId(req.PatientId)
	if err != nil {
		middlewares.Logger.Println("Unmarshal resp3013 failed ", err)
		return nil, 0, err
	}
	return data, total, nil
}

func (op *OutPatientService) FindByOrderSn(orderSn string) (*models.PrescriptionModel, error) {
	pm := &models.PrescriptionModel{}
	data, has, err := pm.FindByOrderSn(orderSn)
	if err != nil {
		middlewares.Logger.Println("FindByOrderSn failed ", err)
		return nil, err
	}
	if !has {
		return nil, errors.New("订单不存在")
	}

	return data, err
}

func (pc *OutPatientService) CancelUpdatePre(req *models.OpCancelManualReq) (*models.Resp4910, error) {
	op := &models.PrescriptionModel{}
	reqHis := &models.Req4910Params{
		CardNo:       req.CardNo,
		PatientId:    req.PatientId,
		InvoiceNoStr: "",
		OrderNo:      req.OrderNo,
	}
	opdata, has, err := op.FindPreByOrderNo(req.OrderNo)
	if err != nil {
		middlewares.Logger.Println("CancelUpdatePre failed ", err)
		return nil, err
	}
	if !has {
		return nil, errors.New("订单不存在")
	}
	if opdata.Status == "charge" {
		reqHis.InvoiceNoStr = opdata.InvoiceNo
		data, err := (&HisService{}).CancelCharge(reqHis)
		if err != nil {
			middlewares.Logger.Println("Unmarshal resp3013 failed ", err)
			return nil, err
		}
		if data.ResultCode != "0" {
			return nil, errors.New(data.ResultMsg)
		}
		oppm := &models.OpPreModel{
			OrderNo:   req.OrderNo,
			PatientId: req.PatientId,
			InvoiceNo: opdata.InvoiceNo,
			Status:    "cancel",
			OrderSn:   req.OrderSn,
		}
		err = op.UpdatePre(oppm)
		if err != nil {
			middlewares.Logger.Println("CancelChargeManual1 failed ", err)
			return nil, err
		}
		op.Remark = "患者手动取消预结算"
		op.InvoiceNo = opdata.InvoiceNo
		op.PatientId = req.PatientId
		op.OrderSn = req.OrderSn

		err = op.CancelPreOrder()
		if err != nil {
			middlewares.Logger.Println("CancelChargeManual2 failed ", err)
			return nil, err
		}
		return data, nil
	}
	return nil, errors.New("订单状态错误")
}
